package com.cloudbroker.bcs.common.aspect;

import java.lang.reflect.Method;
import java.util.Map;

import com.cloudbroker.bcs.common.constants.BasicFields;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.cloudbroker.bcs.common.annotation.BizServiceMark;
import com.cloudbroker.bcs.common.context.BizDataContext;
import com.cloudbroker.bcs.common.service.ErrorDescService;
import com.cloudbroker.bcs.common.util.PrintUtil;

public class ErrorDescAspect {
    
    private static final String CLASS_NAME = ErrorDescAspect.class.getName();
    
    private static final Logger LOGGER = LoggerFactory.getLogger(CLASS_NAME);
    
    private String bizServiceNamePrefix = "";
    
    private ErrorDescService errorDescService;
    
    public ErrorDescAspect() {
        PrintUtil.printComponentLoaded(LOGGER, CLASS_NAME);
    }
    
    public Object handleErrorDesc(ProceedingJoinPoint pjp) throws Throwable {
        setBizServiceName(pjp);
        Object result = null;
        try {
            result = pjp.proceed();
            descError(result);
        } finally {
            clearBinding();
        }
        return result;
    }
    
    private void setBizServiceName(ProceedingJoinPoint pjp) {
        try {
            // 在Spring的环境里，signature就是MethodSignature
            MethodSignature methodSignature = (MethodSignature) pjp.getSignature();
            // 获取Method
            Method method = methodSignature.getMethod();
            String bizServiceName = null;
            // 如果方法上声明了@BizServiceMark，则取其name
            if (method.isAnnotationPresent(BizServiceMark.class)) {
                BizServiceMark bizServiceMark = method.getAnnotation(BizServiceMark.class);
                bizServiceName = bizServiceMark.name();
            }
            // 如果空白，使用方法名
            if (StringUtils.isBlank(bizServiceName)) {
                bizServiceName = bizServiceNamePrefix + method.getName();
            }
            BizDataContext.setBizServiceName(bizServiceName);
        } catch (Exception e) {
            LOGGER.warn("setBizServiceName failed", e);
        }
    }
    
    private void descError(Object result) {
        try {
            errorDescService.descriptError(result);
        } catch (Exception e) {
            LOGGER.warn("descError failed", e);
        }
    }
    
    private void clearBinding() {
        BizDataContext.removeBizServiceName();
    }
    
    public void setBizServiceNamePrefix(String bizServiceNamePrefix) {
        if (StringUtils.isNotBlank(bizServiceNamePrefix)) {
            this.bizServiceNamePrefix = bizServiceNamePrefix;
        }
    }
    
    public void setErrorDescService(ErrorDescService errorDescService) {
        this.errorDescService = errorDescService;
    }
    
}
